import xml.etree.ElementTree as ET
import openpyxl
from openpyxl.styles import Alignment
import sys
import os

def parse_xml_to_excel(xml_file):
    # 解析XML文件
    tree = ET.parse(xml_file)
    root = tree.getroot()
    
    # 创建Excel工作簿
    wb = openpyxl.Workbook()
    
    # 处理第一个sheet：total
    process_total_sheet(wb, root)
    
    # 处理第二个sheet：module
    process_module_sheet(wb, root)
    
    # 处理第三个sheet：TestCase
    process_testcase_sheet(wb, root)
    
    # 处理第四个sheet：failed_testcase
    process_failed_testcase_sheet(wb, root)
    
    # 保存Excel文件
    base_name = os.path.splitext(xml_file)[0]
    excel_file = f"{base_name}.xlsx"
    wb.save(excel_file)
    print(f"Excel文件已生成: {excel_file}")

def process_total_sheet(wb, root):
    """处理第一个sheet：total"""
    if 'total' in wb.sheetnames:
        ws_total = wb['total']
    else:
        ws_total = wb.active
        ws_total.title = 'total'
    
    # 设置表头
    headers = ['', 'pass', 'failed', 'modules_done', 'modules_total']
    for col, header in enumerate(headers, 1):
        ws_total.cell(row=1, column=col, value=header)
    
    # 查找Summary元素
    summary = root.find('Summary')
    if summary is not None:
        data = [
            '',
            summary.get('pass', ''),
            summary.get('failed', ''),
            summary.get('modules_done', ''),
            summary.get('modules_total', '')
        ]
        for col, value in enumerate(data, 1):
            ws_total.cell(row=2, column=col, value=value)

def process_module_sheet(wb, root):
    """处理第二个sheet：module"""
    ws_module = wb.create_sheet('module')
    
    # 设置表头
    headers = ['abi', 'module_name', 'done', 'pass', 'total_tests', 'fail', 'ASSUMPTION_FAILURE', 'IGNORED', 'Reason message']
    for col, header in enumerate(headers, 1):
        ws_module.cell(row=1, column=col, value=header)
    
    row = 2
    # 遍历所有Module元素
    for module in root.findall('Module'):
        # 获取模块基本信息
        abi = module.get('abi', '')
        name = module.get('name', '')
        done = module.get('done', '')
        pass_count = module.get('pass', '0')
        total_tests = module.get('total_tests', '0')
        
        # 统计各种状态的数量
        fail_count = 0
        assumption_failure_count = 0
        ignored_count = 0
        reason_message = ''
        
        # 如果done=false，查找Reason
        if done.lower() == 'false':
            reason_elem = module.find('Reason')
            if reason_elem is not None:
                reason_message = reason_elem.get('message', '')
        
        # 遍历TestCase统计状态
        for testcase in module.findall('TestCase'):
            for test in testcase.findall('Test'):
                result = test.get('result', '')
                if result == 'fail':
                    fail_count += 1
                elif result == 'ASSUMPTION_FAILURE':
                    assumption_failure_count += 1
                elif result == 'IGNORED':
                    ignored_count += 1
        
        # 写入数据
        data = [abi, name, done, pass_count, total_tests, fail_count, assumption_failure_count, ignored_count, reason_message]
        for col, value in enumerate(data, 1):
            ws_module.cell(row=row, column=col, value=value)
        
        row += 1

def process_testcase_sheet(wb, root):
    """处理第三个sheet：TestCase"""
    ws_testcase = wb.create_sheet('TestCase')
    
    # 设置表头
    headers = ['Module', 'name', 'result', 'reason']
    for col, header in enumerate(headers, 1):
        ws_testcase.cell(row=1, column=col, value=header)
    
    row = 2
    module_data = {}  # 用于记录每个module的行范围，以便合并
    
    # 遍历所有Module元素
    for module in root.findall('Module'):
        module_name = module.get('name', '')
        start_row = row
        
        # 遍历该Module下的所有TestCase
        for testcase in module.findall('TestCase'):
            testcase_name = testcase.get('name', '')
            
            # 遍历该TestCase下的所有Test
            for test in testcase.findall('Test'):
                test_name = test.get('name', '')
                result = test.get('result', '')
                
                # 组合name：TestCase name#Test name
                combined_name = f"{testcase_name}#{test_name}"
                
                # 处理reason
                reason = ''
                if result != 'pass':
                    # 查找Failure和StackTrace
                    failure = test.find('Failure')
                    stack_trace = test.find('StackTrace')
                    
                    if failure is not None:
                        reason += f"Failure: {failure.get('message', '')}"
                    if stack_trace is not None and stack_trace.text:
                        if reason:
                            reason += '\n'
                        reason += f"StackTrace: {stack_trace.text}"
                
                # 写入数据
                ws_testcase.cell(row=row, column=1, value=module_name)  # Module
                ws_testcase.cell(row=row, column=2, value=combined_name)  # name
                ws_testcase.cell(row=row, column=3, value=result)  # result
                ws_testcase.cell(row=row, column=4, value=reason)  # reason
                
                row += 1
        
        end_row = row - 1
        if start_row < end_row:
            module_data[module_name] = (start_row, end_row)
    
    # 合并相同module的单元格
    for module_name, (start_row, end_row) in module_data.items():
        if start_row < end_row:
            ws_testcase.merge_cells(f'A{start_row}:A{end_row}')
            # 设置垂直居中
            for r in range(start_row, end_row + 1):
                ws_testcase[f'A{r}'].alignment = Alignment(vertical='center')

def process_failed_testcase_sheet(wb, root):
    """处理第四个sheet：failed_testcase"""
    ws_failed = wb.create_sheet('failed_testcase')
    
    # 设置表头
    headers = ['Module', 'name', 'result', 'reason']
    for col, header in enumerate(headers, 1):
        ws_failed.cell(row=1, column=col, value=header)
    
    row = 2
    module_data = {}  # 用于记录每个module的行范围，以便合并
    
    # 遍历所有Module元素，只收集failed的TestCase
    for module in root.findall('Module'):
        module_name = module.get('name', '')
        start_row = row
        has_failed_cases = False
        
        # 遍历该Module下的所有TestCase
        for testcase in module.findall('TestCase'):
            testcase_name = testcase.get('name', '')
            
            # 遍历该TestCase下的所有Test，只处理result="fail"的
            for test in testcase.findall('Test'):
                if test.get('result') == 'fail':
                    has_failed_cases = True
                    test_name = test.get('name', '')
                    
                    # 组合name：TestCase name#Test name
                    combined_name = f"{testcase_name}#{test_name}"
                    
                    # 处理reason
                    reason = ''
                    # 查找Failure和StackTrace
                    failure = test.find('Failure')
                    stack_trace = test.find('StackTrace')
                    
                    if failure is not None:
                        reason += f"Failure: {failure.get('message', '')}"
                    if stack_trace is not None and stack_trace.text:
                        if reason:
                            reason += '\n'
                        reason += f"StackTrace: {stack_trace.text}"
                    
                    # 写入数据
                    ws_failed.cell(row=row, column=1, value=module_name)  # Module
                    ws_failed.cell(row=row, column=2, value=combined_name)  # name
                    ws_failed.cell(row=row, column=3, value='fail')  # result
                    ws_failed.cell(row=row, column=4, value=reason)  # reason
                    
                    row += 1
        
        end_row = row - 1
        if has_failed_cases and start_row < end_row:
            module_data[module_name] = (start_row, end_row)
    
    # 合并相同module的单元格
    for module_name, (start_row, end_row) in module_data.items():
        if start_row < end_row:
            ws_failed.merge_cells(f'A{start_row}:A{end_row}')
            # 设置垂直居中
            for r in range(start_row, end_row + 1):
                ws_failed[f'A{r}'].alignment = Alignment(vertical='center')

def main():
    if len(sys.argv) != 2:
        print("使用方法: python readXMLToExcel.py <xml文件>")
        sys.exit(1)
    
    xml_file = sys.argv[1]
    
    if not os.path.exists(xml_file):
        print(f"错误: 文件 '{xml_file}' 不存在")
        sys.exit(1)
    
    try:
        parse_xml_to_excel(xml_file)
    except Exception as e:
        print(f"处理XML文件时出错: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()